Secciones

Referencias

International aid may take the form of multilateral aid – provided through international bodies such as the UN, or NGOs such as Oxfam – or bilateral aid, which operates on a government-to-government basis. There is considerable debate about whether international aid works, in the sense of reducing poverty and stimulating development.

However, the effectiveness of aid is often diluted by corruption. Aid is invariably channeled through the governments of recipient countries, in which power is often concentrated in the hands of a few politicians and bureaucrats, and the mechanisms of accountability are, at best, poorly developed. This tends to benefit corrupt leaders and elites rather than the people, projects and programs for which it was intended.

Watts, Carl. (2014). Re: Does foreign aid help the developing countries towards development?. Retrieved from: https://www.researchgate.net/post/Does_foreign_aid_help_the_developing_countries_towards_development/5322005ed039b1e7648b459c/citation/download.

The hypothesis that foreign aid can promote growth in developing countries was explored, using panel data series for foreign aid, while accounting for regional differences in Asian, African, Latin American, and the Caribbean countries as well as the differences in income levels, the results of this study also indicate that foreign aid has mixed effects on economic growth in developing countries.

Ekanayake, E. & Chatrna, Dasha. (2010). The effect of foreign aid on economic growth in developing countries. Journal of International Business and Cultural Studies. 3.

This study examines the relationships between foreign aid, institutional structure, and economic performance for 80 countries in Europe, America, Africa, and Asia. It is found that official development assistance and the quality of institutional structure in the sample countries affect economic growth positively.

Hayaloğlu, Pınar. (2023). Foreign Aid, Institutions, and Economic Performance in Developing Countries. Eskişehir Osmangazi Üniversitesi İktisadi ve İdari Bilimler Dergisi. 18. 748-765. 10.17153/oguiibf.1277348.

Manual para replicar

Cargando Librerias

Algunas librerias y paquetes usados para obtener y descargar los datos

library(tidyverse) # manejo de dataframes
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
Warning: replacing previous import ‘lifecycle::last_warnings’ by ‘rlang::last_warnings’ when loading ‘hms’── Attaching packages ─────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✓ ggplot2 3.3.5     ✓ purrr   0.3.4
✓ tibble  3.1.2     ✓ dplyr   1.0.7
✓ tidyr   1.1.3     ✓ stringr 1.4.0
✓ readr   2.0.1     ✓ forcats 0.5.1
── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
Warning messages:
1: replacing previous import ‘lifecycle::last_warnings’ by ‘rlang::last_warnings’ when loading ‘tibble’ 
2: replacing previous import ‘lifecycle::last_warnings’ by ‘rlang::last_warnings’ when loading ‘pillar’ 
library(reshape2)  # para tranfromar data de long a wide

Attaching package: ‘reshape2’

The following object is masked from ‘package:tidyr’:

    smiths
library(WDI)       # libreria para acceder a metadata de banco mundial
library(readxl)    # leer archivos de excel
library(readr)     # leer archivos csv
library(visdat)    # visualizacion de datos como graficos
library(plotly)    # graficos

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(purrr)     # funcion map
library(plm)       # modelos lineales para datos panel

Attaching package: ‘plm’

The following objects are masked from ‘package:dplyr’:

    between, lag, lead
library(car)       # test y utilidades para modelos
Loading required package: carData

Attaching package: ‘car’

The following object is masked from ‘package:dplyr’:

    recode

The following object is masked from ‘package:purrr’:

    some
library(htmltools) # para imprimir graficos en html

Obtener datos

Datos para paises bajos ingresos sean utilizados, segun clasificación del banco mundial, hay 26 paises de bajos ingresos y 51 de ingresos medios bajos

country_class <- read_excel("CLASS.xlsx")

country_class %>%
  filter(!is.na(Region), !is.na(`Income group`)) %>%
  group_by(`Income group`) %>%
  summarise(countries = n()) %>%
  arrange(factor(`Income group`, levels = c('High income', 'Upper middle income', 'Lower middle income', 'Low income')))

Listado de paises a analisar:

my_countries <- country_class %>%
  filter(!is.na(Region), `Income group` %in% c('Low income', 'Lower middle income')) %>%
  select(Code)
my_countries %>% merge(country_class) %>% select(Code, Economy)

Hacer la respectiva asociacion de nombres iso3c e iso2c

my_countries$iso2c <- WDI_data$country %>%
  filter(iso3c %in% my_countries$Code) %>%
  .$iso2c
my_countries

Datos del banco mundial (para ODA y los indices de gobernanza) y el Human Development Reports API son descargados desde scripts de Python. Son almacenados en archivos CSV y luego son cargados aqui:

cargar HDI

datos_HDI <- read_csv("datos_python_HDI.csv", col_names = c('Code', 'iso2c', 'indicator', 'year', 'value'), 
                      col_types = list(col_character(), col_character(), col_character(), col_double(), col_double()))

hdi_indicators <- datos_HDI %>% distinct(indicator) %>% .$indicator

cargar ODA, GDP, POP.GROW

oda_indicators <- c(
'DT_ODA_ALLD_CD',
'DT_ODA_ALLD_KD',
'DT_ODA_OATL_CD',
'DT_ODA_OATL_KD',
'DT_ODA_ODAT_CD',
'DT_ODA_ODAT_GI_ZS',
'DT_ODA_ODAT_GN_ZS',
'DT_ODA_ODAT_KD',
'DT_ODA_ODAT_MP_ZS',
'DT_ODA_ODAT_PC_ZS',
'DT_ODA_ODAT_XP_ZS'
)
gob_indicators <- c(
'CC_EST',
'CC_NO_SRC',
'CC_PER_RNK',
'CC_PER_RNK_LOWER',
'CC_PER_RNK_UPPER',
'CC_STD_ERR',
'GE_EST',
'GE_NO_SRC',
'GE_PER_RNK',
'GE_PER_RNK_LOWER',
'GE_PER_RNK_UPPER',
'GE_STD_ERR',
'PV_EST',
'PV_NO_SRC',
'PV_PER_RNK',
'PV_PER_RNK_LOWER',
'PV_PER_RNK_UPPER',
'PV_STD_ERR',
'RQ_EST',
'RQ_NO_SRC',
'RQ_PER_RNK',
'RQ_PER_RNK_LOWER',
'RQ_PER_RNK_UPPER',
'RQ_STD_ERR',
'RL_EST',
'RL_NO_SRC',
'RL_PER_RNK',
'RL_PER_RNK_LOWER',
'RL_PER_RNK_UPPER',
'RL_STD_ERR',
'VA_EST',
'VA_NO_SRC',
'VA_PER_RNK',
'VA_PER_RNK_LOWER',
'VA_PER_RNK_UPPER',
'VA_STD_ERR'
)
gdp_indicators <- c(
'NY_ADJ_NNTY_PC_CD',
'NY_ADJ_NNTY_PC_KD',
'NY_ADJ_NNTY_PC_KD_ZG',
'NY_GDP_PCAP_CN',
'NY_GDP_PCAP_KN',
'NY_GDP_PCAP_CD',
'NY_GDP_PCAP_KD',
'NY_GDP_MKTP_KD_ZG',
'NY_GDP_DEFL_ZS_AD',
'NY_GDP_DEFL_ZS',
'NY_GDP_MKTP_CD',
'NY_GDP_MKTP_CN',
'NY_GDP_MKTP_KN',
'NY_GDP_MKTP_KD',
'NY_GDP_PCAP_KD_ZG',
'NY_GDP_PCAP_PP_KD',
'NY_GDP_PCAP_PP_CD',
'SL_GDP_PCAP_EM_KD',
'SP_POP_GROW'
)

datos_WB <- data.frame(indicator = character(), iso2c = character(), year = double(), value = double())

suppressWarnings(
  for (indicator in c(oda_indicators, gob_indicators, gdp_indicators)) {
    datos_WB <- rbind(datos_WB, read_csv(paste("datos_python", indicator, ".csv", sep =''), 
                                           col_names = c('indicator', 'iso2c', 'year', 'value'),
                                           col_types = list(col_character(), col_character(), col_double(), col_double())))
  }
)

cargar POVERTY

Poverty <- read_excel("GlobalExtremePovertyDollaraDay_Compact.xlsx", sheet = "Data Long Format")

names(Poverty) <- c("ccode", "country", "year", "value")

Poverty[Poverty=="Cape Verde"] <- "Cabo Verde"
Poverty[Poverty=="Congo"] <- "Congo, Rep."
Poverty[Poverty=="Egypt"] <- "Egypt, Arab Rep."
Poverty[Poverty=="Iran"] <- "Iran, Islamic Rep."
Poverty[Poverty=="Kyrgyzstan"] <- "Kyrgyz Republic"
Poverty[Poverty=="Laos"] <- "Lao PDR"
Poverty[Poverty=="Macedonia"] <- "North Macedonia"
Poverty[Poverty=="Russia"] <- "Russian Federation"
Poverty[Poverty=="Slovakia"] <- "Slovak Republic"
Poverty[Poverty=="South Korea"] <- "Korea, Rep."
Poverty[Poverty=="Swaziland"] <- "Eswatini"
Poverty[Poverty=="Syria"] <- "Syrian Arab Republic"
Poverty[Poverty=="The Gambia"] <- "Gambia, The"
Poverty[Poverty=="Turkey"] <- "Turkiye"
Poverty[Poverty=="Venezuela"] <- "Venezuela, RB"
Poverty[Poverty=="Yemen"] <- "Yemen, Rep."

Poverty <- Poverty %>%
  filter(year > 1994) %>%
  merge(WDI_data$country, all.x = TRUE) %>%
  mutate(indicator = 'POV') %>%
  merge(my_countries) %>%
  select(indicator, iso2c, year, value)

Manipulacion de Datos

Transformar datos a la estructura wide

datos_paper <- rbind(datos_WB, datos_HDI %>% select(indicator, iso2c, year, value), Poverty) %>%
  pivot_wider(names_from = indicator, values_from = value)

Promedio de Indices de Gobernanza

datos_paper <- datos_paper %>% mutate(GOV =  (CC.EST + GE.EST + PV.EST + RQ.EST + RL.EST + VA.EST) / 6)

Operador Diferencia

datos_paper <- datos_paper %>% arrange(iso2c, year) %>% 
        mutate(hdi_diff = case_when(iso2c == dplyr::lag(iso2c) ~ hdi - dplyr::lag(hdi), TRUE ~ NA_real_), 
               NY.GDP.PCAP.CD_diff = case_when(iso2c == dplyr::lag(iso2c) ~ NY.GDP.PCAP.CD - dplyr::lag(NY.GDP.PCAP.CD), TRUE ~ NA_real_),
               DT.ODA.ALLD.CD_diff = case_when(iso2c == dplyr::lag(iso2c) ~ DT.ODA.ALLD.CD - dplyr::lag(DT.ODA.ALLD.CD), TRUE ~ NA_real_),
               DT.ODA.ODAT.PC.ZS_diff = case_when(iso2c == dplyr::lag(iso2c) ~ DT.ODA.ODAT.PC.ZS - dplyr::lag(DT.ODA.ODAT.PC.ZS), TRUE ~ NA_real_),
               GOV_diff = case_when(iso2c == dplyr::lag(iso2c) ~ GOV - dplyr::lag(GOV), TRUE ~ NA_real_),
               POV_diff = case_when(iso2c == dplyr::lag(iso2c) ~ POV - dplyr::lag(POV), TRUE ~ NA_real_))

ODA

vis_dat(datos_paper %>% select(all_of(gsub("_", ".", oda_indicators)))) 

  # DT.ODA.OATL.CD and DT.ODA.OATL.KD faltan
  # DT.ODA.ODAT.GI.ZS, DT.ODA.ODAT.GN.ZS, DT.ODA.ODAT.MP.ZS and DT.ODA.ODAT.XP.ZS tienen faltas
  # Un par de ocurrencias pais-año que faltan datos

GDP

vis_dat(datos_paper %>% select(NY.GDP.PCAP.CN, NY.GDP.PCAP.CD)) 

  # NY.GDP.PCAP.CN, NY.GDP.PCAP.CD, NY.GDP.MKTP.CD, NY.GDP.MKTP.CN son buenos candidatos para usar como variables, 
  # 'SY'falta PIB per Capita en 2022, 2023 sin datos algunos paises

GOV

vis_dat(datos_paper %>% arrange(year) %>% select(all_of(gsub("_", ".", gob_indicators)))) 

  # Datos del 2000 para atras tienen espacios faltantes 

HDI

vis_dat(datos_paper %>% select(all_of(hdi_indicators))) 

  # abr, co2_prod, le, le_f, le_m, mmr son las pocas categorias sin datos faltantes
  # hdi faltante en multiples ocaciones

POP.GROW

vis_dat(datos_paper %>% arrange(iso2c) %>% select(SP.POP.GROW)) 

  # ZW no tiene datos de crecimiento poblacional

POV

vis_dat(datos_paper %>% arrange(iso2c) %>% select(POV)) 

  # Hay muchos paises sin datos

Modelos OLS

Filtros para modelo

# variables de etiqueta
ve <- c('iso2c', 'year')
# variables depndientes
vd <- c('hdi', 'hdi_diff', 'NY.GDP.PCAP.CD', 'NY.GDP.PCAP.CD_diff')
# variables independientes
vi <- c('DT.ODA.ALLD.CD', 'DT.ODA.ALLD.CD_diff', 'DT.ODA.ODAT.PC.ZS', 'DT.ODA.ODAT.PC.ZS_diff', 
        'SP.POP.GROW', 'GOV') #'CC.EST', 'GE.EST', 'PV.EST', 'RQ.EST', 'RL.EST', 'VA.EST', 'GOV_diff', 'POV', 'POV_diff'

# paises sin datos
delete_c <- c('SS', 'ZW', 'BT', 'ER', 'GW', 'KP', 'LB', 'NG', 'PS', 'SO', 'VU', 'FM', 'KI', 'TL', 'CV', 'SB', 'SY')
# años sin datos
first_y <- 2002
last_y <- 2022

datos_model <- datos_paper %>% 
  filter(!iso2c %in% delete_c, !year <  first_y, !year > last_y) %>%
  select(all_of(c(ve, vd, vi)))

datos_model
vis_dat(datos_model)

Relaciones

Se revisara las relaciones entre las variables graficamente No se ve una relacion clara, hay tanto paises con punteos altos y bajos de GOB que tienen tanto HID altos o bajos Quiza puede verse una leve relacion de mayor punteo en GOB acompañado de mejor punteo den HDI Los datos de GPD si muestran una relacion positiva con el HDI visto en las graficas

HDI

HDI diff

GPD.PC

GPD.PC diff

Modelos Regresion Lineal

Probando modelos sencillos, regresion lineal, Minimos cuadrados, datos panel, HDI o GDP o sus differecias

HDI

ODA.ALL

summary(models[[keys[1]]])

Call:
lm(formula = f, data = datos_model)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.23055 -0.05445 -0.00579  0.05112  0.56380 

Coefficients:
                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)     6.703e-01  6.959e-03   96.33  < 2e-16 ***
DT.ODA.ALLD.CD  1.115e-11  2.353e-12    4.74 2.38e-06 ***
SP.POP.GROW    -4.422e-02  2.551e-03  -17.34  < 2e-16 ***
GOV             7.339e-02  5.517e-03   13.30  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.08798 on 1256 degrees of freedom
Multiple R-squared:  0.3091,    Adjusted R-squared:  0.3074 
F-statistic: 187.3 on 3 and 1256 DF,  p-value: < 2.2e-16

ODA.ALL_diff

HDI = ODA.ALL_diff + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[2]]])
# Todas las variables son significativas al 99% excepto ODA.ALL_diff y Regulatory Quality

ODA.PC

HDI = ODA.PC + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[3]]])
# Todas las variables son significativas al 99% excepto Regulatory Quality

ODA.PC_diff

HDI = ODA.PC_diff + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[4]]])
# Todas las variables son significativas al 99% excepto  ODA.ALL_diff y Regulatory Quality

HDI_diff

ODA.ALL

HDI_diff = ODA.ALL + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[5]]])
# Todas las variables son significativas al 95% excepto ODA.ALL, Control of Corruption y Rule of Law

ODA.ALL_diff

HDI_diff = ODA.ALL_diff + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[6]]])
# Todas las variables son significativas al 95% excepto Control of Corruption y Voice and Accountability

ODA.PC

HDI_diff = ODA.PC + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[7]]])
# Todas las variables son significativas al 95% excepto Rule of Law y Voice and Accountability

ODA.PC_diff

HDI_diff = ODA.PC_diff + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[8]]])
# Todas las variables son significativas al 95% excepto Control of Corruption y Voice and Accountability

GPD.PC

ODA.ALL

GPD.PC = ODA.ALL + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[9]]])
# Todas las variables son significativas al 99% excepto ODA.ALL, Control of Corruption, Regulatory Quality y Rule of Law

ODA.ALL_diff

GPD.PC = ODA.ALL + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[10]]])
# Todas las variables son significativas al 99% excepto ODA.ALL_diff, Control of Corruption, Regulatory Quality y Rule of Law

ODA.PC

GPD.PC = ODA.PC + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[11]]])
# Todas las variables son significativas al 99% excepto Rule of Law

ODA.PC_diff

GPD.PC = ODA.PC_diff + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[12]]])
# Todas las variables son significativas al 99% excepto ODA.ALL_diff, Control of Corruption, Regulatory Quality y Rule of Law

GPD.PC_diff

ODA.ALL

GPD.PC_diff = ODA.ALL + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[13]]])
# Todas las variables son significativas al 95% excepto ODA.ALL, Control of Corruption, Regulatory Quality y Voice and Accountability

ODA.ALL_diff

GPD.PC_diff = ODA.ALL + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[14]]])
# Todas las variables son significativas al 95% excepto ODA.ALL_diff, Control of Corruption, Regulatory Quality y Voice and Accountability

ODA.PC

GPD.PC_diff = ODA.PC + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[15]]])
# Todas las variables son significativas al 95% excepto ODA.PC, Control of Corruption, Political Stability, Regulatory Quality y Voice and Accountability

ODA.PC_diff

GPD.PC_diff = ODA.PC_diff + CC + GE + PV + RQ + RL + VA + POP.GROW

summary(models[[keys[16]]])
# Todas las variables son significativas al 95% excepto ODA.PC_diff, Control of Corruption, Regulatory Quality y Voice and Accountability

Modelos Efectos fijos

HDI ~ ODA.ALL

plm(hdi ~ DT.ODA.ALLD.CD + GOV + SP.POP.GROW, data=datos_model,
    index = c("iso2c", "year"), model = "within")

# summary(lm(hdi ~ DT.ODA.ALLD.CD + CC.EST + GE.EST + PV.EST + RQ.EST + RL.EST + VA.EST + SP.POP.GROW + iso2c, data=datos_model))
# Corruption Control, Government Effectiveness, Political Stability y Voice and Accountability no son significativas

HDI ~ ODA.PC

plm(hdi ~ DT.ODA.ODAT.PC.ZS + GOV + SP.POP.GROW, data=datos_model,
    index = c("iso2c", "year"), model = "within")

#summary(lm(hdi ~ DT.ODA.ODAT.PC.ZS + CC.EST + GE.EST + PV.EST + RQ.EST + RL.EST + VA.EST + SP.POP.GROW + iso2c, data=datos_model))
# Corruption Control, Government Effectiveness y Voice and Accountability no son significativas

GDP.PC ~ ODA.ALL

plm(NY.GDP.PCAP.CD ~ DT.ODA.ALLD.CD + GOV + SP.POP.GROW, data=datos_model,
    index = c("iso2c", "year"), model = "within")

#summary(lm(NY.GDP.PCAP.CD ~ DT.ODA.ALLD.CD + CC.EST + GE.EST + PV.EST + RQ.EST + RL.EST + VA.EST + SP.POP.GROW + iso2c, data=datos_model))
# Intercepto, Corruption Control, Regulatory Quality, Rule of Law, Voice and Accountability y Population Growth no son significativas

GDP.PC ~ ODA.PC

plm(NY.GDP.PCAP.CD ~ DT.ODA.ODAT.PC.ZS + GOV + SP.POP.GROW, data=datos_model,
    index = c("iso2c", "year"), model = "within")

#summary(lm(NY.GDP.PCAP.CD ~ DT.ODA.ODAT.PC.ZS + CC.EST + GE.EST + PV.EST + RQ.EST + RL.EST + VA.EST + SP.POP.GROW + iso2c, data=datos_model))
# Corruption Control, Regulatory Quality, Rule of Law y Voice and Accountability no son significativas
LS0tDQp0aXRsZTogIk9mZmljaWFsIERldmVsb3BtZW50IEFzc2lzdGFuY2UgYW5kIEluc3RpdHV0aW9uYWwgUXVhbGl0eSBvbiBVbmRldmVsb3BlZCBjb3VudHJpZXMiDQphdXRob3I6ICJPc2NhciBFZHVhcmRvIE1vcmFsZXMgQ8OhcmRlbmFzIg0KZGF0ZTogIjIwMjQtMDgtMDUiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KIyBTZWNjaW9uZXMgey50YWJzZXQgLnRhYnNldC1mYWRlfQ0KDQojIyBSZWZlcmVuY2lhcw0KDQpJbnRlcm5hdGlvbmFsIGFpZCBtYXkgdGFrZSB0aGUgZm9ybSBvZiBtdWx0aWxhdGVyYWwgYWlkIC0tIHByb3ZpZGVkIHRocm91Z2ggaW50ZXJuYXRpb25hbCBib2RpZXMgc3VjaCBhcyB0aGUgVU4sIG9yIE5HT3Mgc3VjaCBhcyBPeGZhbSAtLSBvciBiaWxhdGVyYWwgYWlkLCB3aGljaCBvcGVyYXRlcyBvbiBhIGdvdmVybm1lbnQtdG8tZ292ZXJubWVudCBiYXNpcy4gVGhlcmUgaXMgY29uc2lkZXJhYmxlIGRlYmF0ZSBhYm91dCB3aGV0aGVyIGludGVybmF0aW9uYWwgYWlkIHdvcmtzLCBpbiB0aGUgc2Vuc2Ugb2YgcmVkdWNpbmcgcG92ZXJ0eSBhbmQgc3RpbXVsYXRpbmcgZGV2ZWxvcG1lbnQuDQoNCkhvd2V2ZXIsIHRoZSBlZmZlY3RpdmVuZXNzIG9mIGFpZCBpcyBvZnRlbiBkaWx1dGVkIGJ5IGNvcnJ1cHRpb24uIEFpZCBpcyBpbnZhcmlhYmx5IGNoYW5uZWxlZCB0aHJvdWdoIHRoZSBnb3Zlcm5tZW50cyBvZiByZWNpcGllbnQgY291bnRyaWVzLCBpbiB3aGljaCBwb3dlciBpcyBvZnRlbiBjb25jZW50cmF0ZWQgaW4gdGhlIGhhbmRzIG9mIGEgZmV3IHBvbGl0aWNpYW5zIGFuZCBidXJlYXVjcmF0cywgYW5kIHRoZSBtZWNoYW5pc21zIG9mIGFjY291bnRhYmlsaXR5IGFyZSwgYXQgYmVzdCwgcG9vcmx5IGRldmVsb3BlZC4gVGhpcyB0ZW5kcyB0byBiZW5lZml0IGNvcnJ1cHQgbGVhZGVycyBhbmQgZWxpdGVzIHJhdGhlciB0aGFuIHRoZSBwZW9wbGUsIHByb2plY3RzIGFuZCBwcm9ncmFtcyBmb3Igd2hpY2ggaXQgd2FzIGludGVuZGVkLg0KDQpfX1dhdHRzLCBDYXJsLiAoMjAxNCkuIFJlOiBEb2VzIGZvcmVpZ24gYWlkIGhlbHAgdGhlIGRldmVsb3BpbmcgY291bnRyaWVzIHRvd2FyZHMgZGV2ZWxvcG1lbnQ/LiBSZXRyaWV2ZWQgZnJvbTpfXyBodHRwczovL3d3dy5yZXNlYXJjaGdhdGUubmV0L3Bvc3QvRG9lc19mb3JlaWduX2FpZF9oZWxwX3RoZV9kZXZlbG9waW5nX2NvdW50cmllc190b3dhcmRzX2RldmVsb3BtZW50LzUzMjIwMDVlZDAzOWIxZTc2NDhiNDU5Yy9jaXRhdGlvbi9kb3dubG9hZC4NCg0KVGhlIGh5cG90aGVzaXMgdGhhdCBmb3JlaWduIGFpZCBjYW4gcHJvbW90ZSBncm93dGggaW4gZGV2ZWxvcGluZyBjb3VudHJpZXMgd2FzIGV4cGxvcmVkLCB1c2luZyBwYW5lbCBkYXRhIHNlcmllcyBmb3IgZm9yZWlnbiBhaWQsIHdoaWxlIGFjY291bnRpbmcgZm9yIHJlZ2lvbmFsIGRpZmZlcmVuY2VzIGluIEFzaWFuLCBBZnJpY2FuLCBMYXRpbiBBbWVyaWNhbiwgYW5kIHRoZSBDYXJpYmJlYW4gY291bnRyaWVzIGFzIHdlbGwgYXMgdGhlIGRpZmZlcmVuY2VzIGluIGluY29tZSBsZXZlbHMsIHRoZSByZXN1bHRzIG9mIHRoaXMgc3R1ZHkgYWxzbyBpbmRpY2F0ZSB0aGF0IGZvcmVpZ24gYWlkIGhhcyBtaXhlZCBlZmZlY3RzIG9uIGVjb25vbWljIGdyb3d0aCBpbiBkZXZlbG9waW5nIGNvdW50cmllcy4NCg0KX19Fa2FuYXlha2UsIEUuICYgQ2hhdHJuYSwgRGFzaGEuICgyMDEwKS4gVGhlIGVmZmVjdCBvZiBmb3JlaWduIGFpZCBvbiBlY29ub21pYyBncm93dGggaW4gZGV2ZWxvcGluZyBjb3VudHJpZXMuIEpvdXJuYWwgb2YgSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBhbmQgQ3VsdHVyYWwgU3R1ZGllcy4gMy5fXw0KDQpUaGlzIHN0dWR5IGV4YW1pbmVzIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gZm9yZWlnbiBhaWQsIGluc3RpdHV0aW9uYWwgc3RydWN0dXJlLCBhbmQgZWNvbm9taWMgcGVyZm9ybWFuY2UgZm9yIDgwIGNvdW50cmllcyBpbiBFdXJvcGUsIEFtZXJpY2EsIEFmcmljYSwgYW5kIEFzaWEuIEl0IGlzIGZvdW5kIHRoYXQgb2ZmaWNpYWwgZGV2ZWxvcG1lbnQgYXNzaXN0YW5jZSBhbmQgdGhlIHF1YWxpdHkgb2YgaW5zdGl0dXRpb25hbCBzdHJ1Y3R1cmUgaW4gdGhlIHNhbXBsZSBjb3VudHJpZXMgYWZmZWN0IGVjb25vbWljIGdyb3d0aCBwb3NpdGl2ZWx5Lg0KDQpfX0hheWFsb8SfbHUsIFDEsW5hci4gKDIwMjMpLiBGb3JlaWduIEFpZCwgSW5zdGl0dXRpb25zLCBhbmQgRWNvbm9taWMgUGVyZm9ybWFuY2UgaW4gRGV2ZWxvcGluZyBDb3VudHJpZXMuIEVza2nFn2VoaXIgT3NtYW5nYXppIMOcbml2ZXJzaXRlc2kgxLBrdGlzYWRpIHZlIMSwZGFyaSBCaWxpbWxlciBEZXJnaXNpLiAxOC4gNzQ4LTc2NS4gMTAuMTcxNTMvb2d1aWliZi4xMjc3MzQ4Ll9fDQoNCiMjIE1hbnVhbCBwYXJhIHJlcGxpY2FyDQoNCiMjIyBDYXJnYW5kbyBMaWJyZXJpYXMNCg0KQWxndW5hcyBsaWJyZXJpYXMgeSBwYXF1ZXRlcyB1c2Fkb3MgcGFyYSBvYnRlbmVyIHkgZGVzY2FyZ2FyIGxvcyBkYXRvcw0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKSAjIG1hbmVqbyBkZSBkYXRhZnJhbWVzDQpsaWJyYXJ5KHJlc2hhcGUyKSAgIyBwYXJhIHRyYW5mcm9tYXIgZGF0YSBkZSBsb25nIGEgd2lkZQ0KbGlicmFyeShXREkpICAgICAgICMgbGlicmVyaWEgcGFyYSBhY2NlZGVyIGEgbWV0YWRhdGEgZGUgYmFuY28gbXVuZGlhbA0KbGlicmFyeShyZWFkeGwpICAgICMgbGVlciBhcmNoaXZvcyBkZSBleGNlbA0KbGlicmFyeShyZWFkcikgICAgICMgbGVlciBhcmNoaXZvcyBjc3YNCmxpYnJhcnkodmlzZGF0KSAgICAjIHZpc3VhbGl6YWNpb24gZGUgZGF0b3MgY29tbyBncmFmaWNvcw0KbGlicmFyeShwbG90bHkpICAgICMgZ3JhZmljb3MNCmxpYnJhcnkocHVycnIpICAgICAjIGZ1bmNpb24gbWFwDQpsaWJyYXJ5KHBsbSkgICAgICAgIyBtb2RlbG9zIGxpbmVhbGVzIHBhcmEgZGF0b3MgcGFuZWwNCmxpYnJhcnkoY2FyKSAgICAgICAjIHRlc3QgeSB1dGlsaWRhZGVzIHBhcmEgbW9kZWxvcw0KbGlicmFyeShodG1sdG9vbHMpICMgcGFyYSBpbXByaW1pciBncmFmaWNvcyBlbiBodG1sDQpgYGANCg0KIyMjIE9idGVuZXIgZGF0b3MNCg0KRGF0b3MgcGFyYSBwYWlzZXMgYmFqb3MgaW5ncmVzb3Mgc2VhbiB1dGlsaXphZG9zLCBzZWd1biBjbGFzaWZpY2FjacOzbiBkZWwgYmFuY28gbXVuZGlhbCwgaGF5IDI2IHBhaXNlcyBkZSBiYWpvcyBpbmdyZXNvcyB5IDUxIGRlIGluZ3Jlc29zIG1lZGlvcyBiYWpvcw0KDQpgYGB7cn0NCmNvdW50cnlfY2xhc3MgPC0gcmVhZF9leGNlbCgiQ0xBU1MueGxzeCIpDQoNCmNvdW50cnlfY2xhc3MgJT4lDQogIGZpbHRlcighaXMubmEoUmVnaW9uKSwgIWlzLm5hKGBJbmNvbWUgZ3JvdXBgKSkgJT4lDQogIGdyb3VwX2J5KGBJbmNvbWUgZ3JvdXBgKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50cmllcyA9IG4oKSkgJT4lDQogIGFycmFuZ2UoZmFjdG9yKGBJbmNvbWUgZ3JvdXBgLCBsZXZlbHMgPSBjKCdIaWdoIGluY29tZScsICdVcHBlciBtaWRkbGUgaW5jb21lJywgJ0xvd2VyIG1pZGRsZSBpbmNvbWUnLCAnTG93IGluY29tZScpKSkNCmBgYA0KDQpMaXN0YWRvIGRlIHBhaXNlcyBhIGFuYWxpc2FyOg0KDQpgYGB7cn0NCm15X2NvdW50cmllcyA8LSBjb3VudHJ5X2NsYXNzICU+JQ0KICBmaWx0ZXIoIWlzLm5hKFJlZ2lvbiksIGBJbmNvbWUgZ3JvdXBgICVpbiUgYygnTG93IGluY29tZScsICdMb3dlciBtaWRkbGUgaW5jb21lJykpICU+JQ0KICBzZWxlY3QoQ29kZSkNCm15X2NvdW50cmllcyAlPiUgbWVyZ2UoY291bnRyeV9jbGFzcykgJT4lIHNlbGVjdChDb2RlLCBFY29ub215KQ0KYGBgDQoNCkhhY2VyIGxhIHJlc3BlY3RpdmEgYXNvY2lhY2lvbiBkZSBub21icmVzIGlzbzNjIGUgaXNvMmMNCg0KYGBge3J9DQpteV9jb3VudHJpZXMkaXNvMmMgPC0gV0RJX2RhdGEkY291bnRyeSAlPiUNCiAgZmlsdGVyKGlzbzNjICVpbiUgbXlfY291bnRyaWVzJENvZGUpICU+JQ0KICAuJGlzbzJjDQpteV9jb3VudHJpZXMNCmBgYA0KDQpEYXRvcyBkZWwgYmFuY28gbXVuZGlhbCAocGFyYSBPREEgeSBsb3MgaW5kaWNlcyBkZSBnb2Jlcm5hbnphKSB5IGVsIEh1bWFuIERldmVsb3BtZW50IFJlcG9ydHMgQVBJIHNvbiBkZXNjYXJnYWRvcyBkZXNkZSBzY3JpcHRzIGRlIFB5dGhvbi4gU29uIGFsbWFjZW5hZG9zIGVuIGFyY2hpdm9zIENTViB5IGx1ZWdvIHNvbiBjYXJnYWRvcyBhcXVpOg0KDQojIyMgY2FyZ2FyIEhESQ0KDQpgYGB7cn0NCmRhdG9zX0hESSA8LSByZWFkX2NzdigiZGF0b3NfcHl0aG9uX0hESS5jc3YiLCBjb2xfbmFtZXMgPSBjKCdDb2RlJywgJ2lzbzJjJywgJ2luZGljYXRvcicsICd5ZWFyJywgJ3ZhbHVlJyksIA0KICAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGxpc3QoY29sX2NoYXJhY3RlcigpLCBjb2xfY2hhcmFjdGVyKCksIGNvbF9jaGFyYWN0ZXIoKSwgY29sX2RvdWJsZSgpLCBjb2xfZG91YmxlKCkpKQ0KDQpoZGlfaW5kaWNhdG9ycyA8LSBkYXRvc19IREkgJT4lIGRpc3RpbmN0KGluZGljYXRvcikgJT4lIC4kaW5kaWNhdG9yDQpgYGANCg0KIyMjIGNhcmdhciBPREEsIEdEUCwgUE9QLkdST1cNCg0KYGBge3J9DQpvZGFfaW5kaWNhdG9ycyA8LSBjKA0KJ0RUX09EQV9BTExEX0NEJywNCidEVF9PREFfQUxMRF9LRCcsDQonRFRfT0RBX09BVExfQ0QnLA0KJ0RUX09EQV9PQVRMX0tEJywNCidEVF9PREFfT0RBVF9DRCcsDQonRFRfT0RBX09EQVRfR0lfWlMnLA0KJ0RUX09EQV9PREFUX0dOX1pTJywNCidEVF9PREFfT0RBVF9LRCcsDQonRFRfT0RBX09EQVRfTVBfWlMnLA0KJ0RUX09EQV9PREFUX1BDX1pTJywNCidEVF9PREFfT0RBVF9YUF9aUycNCikNCmdvYl9pbmRpY2F0b3JzIDwtIGMoDQonQ0NfRVNUJywNCidDQ19OT19TUkMnLA0KJ0NDX1BFUl9STksnLA0KJ0NDX1BFUl9STktfTE9XRVInLA0KJ0NDX1BFUl9STktfVVBQRVInLA0KJ0NDX1NURF9FUlInLA0KJ0dFX0VTVCcsDQonR0VfTk9fU1JDJywNCidHRV9QRVJfUk5LJywNCidHRV9QRVJfUk5LX0xPV0VSJywNCidHRV9QRVJfUk5LX1VQUEVSJywNCidHRV9TVERfRVJSJywNCidQVl9FU1QnLA0KJ1BWX05PX1NSQycsDQonUFZfUEVSX1JOSycsDQonUFZfUEVSX1JOS19MT1dFUicsDQonUFZfUEVSX1JOS19VUFBFUicsDQonUFZfU1REX0VSUicsDQonUlFfRVNUJywNCidSUV9OT19TUkMnLA0KJ1JRX1BFUl9STksnLA0KJ1JRX1BFUl9STktfTE9XRVInLA0KJ1JRX1BFUl9STktfVVBQRVInLA0KJ1JRX1NURF9FUlInLA0KJ1JMX0VTVCcsDQonUkxfTk9fU1JDJywNCidSTF9QRVJfUk5LJywNCidSTF9QRVJfUk5LX0xPV0VSJywNCidSTF9QRVJfUk5LX1VQUEVSJywNCidSTF9TVERfRVJSJywNCidWQV9FU1QnLA0KJ1ZBX05PX1NSQycsDQonVkFfUEVSX1JOSycsDQonVkFfUEVSX1JOS19MT1dFUicsDQonVkFfUEVSX1JOS19VUFBFUicsDQonVkFfU1REX0VSUicNCikNCmdkcF9pbmRpY2F0b3JzIDwtIGMoDQonTllfQURKX05OVFlfUENfQ0QnLA0KJ05ZX0FESl9OTlRZX1BDX0tEJywNCidOWV9BREpfTk5UWV9QQ19LRF9aRycsDQonTllfR0RQX1BDQVBfQ04nLA0KJ05ZX0dEUF9QQ0FQX0tOJywNCidOWV9HRFBfUENBUF9DRCcsDQonTllfR0RQX1BDQVBfS0QnLA0KJ05ZX0dEUF9NS1RQX0tEX1pHJywNCidOWV9HRFBfREVGTF9aU19BRCcsDQonTllfR0RQX0RFRkxfWlMnLA0KJ05ZX0dEUF9NS1RQX0NEJywNCidOWV9HRFBfTUtUUF9DTicsDQonTllfR0RQX01LVFBfS04nLA0KJ05ZX0dEUF9NS1RQX0tEJywNCidOWV9HRFBfUENBUF9LRF9aRycsDQonTllfR0RQX1BDQVBfUFBfS0QnLA0KJ05ZX0dEUF9QQ0FQX1BQX0NEJywNCidTTF9HRFBfUENBUF9FTV9LRCcsDQonU1BfUE9QX0dST1cnDQopDQoNCmRhdG9zX1dCIDwtIGRhdGEuZnJhbWUoaW5kaWNhdG9yID0gY2hhcmFjdGVyKCksIGlzbzJjID0gY2hhcmFjdGVyKCksIHllYXIgPSBkb3VibGUoKSwgdmFsdWUgPSBkb3VibGUoKSkNCg0Kc3VwcHJlc3NXYXJuaW5ncygNCiAgZm9yIChpbmRpY2F0b3IgaW4gYyhvZGFfaW5kaWNhdG9ycywgZ29iX2luZGljYXRvcnMsIGdkcF9pbmRpY2F0b3JzKSkgew0KICAgIGRhdG9zX1dCIDwtIHJiaW5kKGRhdG9zX1dCLCByZWFkX2NzdihwYXN0ZSgiZGF0b3NfcHl0aG9uIiwgaW5kaWNhdG9yLCAiLmNzdiIsIHNlcCA9JycpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjKCdpbmRpY2F0b3InLCAnaXNvMmMnLCAneWVhcicsICd2YWx1ZScpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGxpc3QoY29sX2NoYXJhY3RlcigpLCBjb2xfY2hhcmFjdGVyKCksIGNvbF9kb3VibGUoKSwgY29sX2RvdWJsZSgpKSkpDQogIH0NCikNCmBgYA0KDQojIyMgY2FyZ2FyIFBPVkVSVFkNCmBgYHtyfQ0KUG92ZXJ0eSA8LSByZWFkX2V4Y2VsKCJHbG9iYWxFeHRyZW1lUG92ZXJ0eURvbGxhcmFEYXlfQ29tcGFjdC54bHN4Iiwgc2hlZXQgPSAiRGF0YSBMb25nIEZvcm1hdCIpDQoNCm5hbWVzKFBvdmVydHkpIDwtIGMoImNjb2RlIiwgImNvdW50cnkiLCAieWVhciIsICJ2YWx1ZSIpDQoNClBvdmVydHlbUG92ZXJ0eT09IkNhcGUgVmVyZGUiXSA8LSAiQ2FibyBWZXJkZSINClBvdmVydHlbUG92ZXJ0eT09IkNvbmdvIl0gPC0gIkNvbmdvLCBSZXAuIg0KUG92ZXJ0eVtQb3ZlcnR5PT0iRWd5cHQiXSA8LSAiRWd5cHQsIEFyYWIgUmVwLiINClBvdmVydHlbUG92ZXJ0eT09IklyYW4iXSA8LSAiSXJhbiwgSXNsYW1pYyBSZXAuIg0KUG92ZXJ0eVtQb3ZlcnR5PT0iS3lyZ3l6c3RhbiJdIDwtICJLeXJneXogUmVwdWJsaWMiDQpQb3ZlcnR5W1BvdmVydHk9PSJMYW9zIl0gPC0gIkxhbyBQRFIiDQpQb3ZlcnR5W1BvdmVydHk9PSJNYWNlZG9uaWEiXSA8LSAiTm9ydGggTWFjZWRvbmlhIg0KUG92ZXJ0eVtQb3ZlcnR5PT0iUnVzc2lhIl0gPC0gIlJ1c3NpYW4gRmVkZXJhdGlvbiINClBvdmVydHlbUG92ZXJ0eT09IlNsb3Zha2lhIl0gPC0gIlNsb3ZhayBSZXB1YmxpYyINClBvdmVydHlbUG92ZXJ0eT09IlNvdXRoIEtvcmVhIl0gPC0gIktvcmVhLCBSZXAuIg0KUG92ZXJ0eVtQb3ZlcnR5PT0iU3dhemlsYW5kIl0gPC0gIkVzd2F0aW5pIg0KUG92ZXJ0eVtQb3ZlcnR5PT0iU3lyaWEiXSA8LSAiU3lyaWFuIEFyYWIgUmVwdWJsaWMiDQpQb3ZlcnR5W1BvdmVydHk9PSJUaGUgR2FtYmlhIl0gPC0gIkdhbWJpYSwgVGhlIg0KUG92ZXJ0eVtQb3ZlcnR5PT0iVHVya2V5Il0gPC0gIlR1cmtpeWUiDQpQb3ZlcnR5W1BvdmVydHk9PSJWZW5lenVlbGEiXSA8LSAiVmVuZXp1ZWxhLCBSQiINClBvdmVydHlbUG92ZXJ0eT09IlllbWVuIl0gPC0gIlllbWVuLCBSZXAuIg0KDQpQb3ZlcnR5IDwtIFBvdmVydHkgJT4lDQogIGZpbHRlcih5ZWFyID4gMTk5NCkgJT4lDQogIG1lcmdlKFdESV9kYXRhJGNvdW50cnksIGFsbC54ID0gVFJVRSkgJT4lDQogIG11dGF0ZShpbmRpY2F0b3IgPSAnUE9WJykgJT4lDQogIG1lcmdlKG15X2NvdW50cmllcykgJT4lDQogIHNlbGVjdChpbmRpY2F0b3IsIGlzbzJjLCB5ZWFyLCB2YWx1ZSkNCg0KYGBgDQoNCg0KIyMjIE1hbmlwdWxhY2lvbiBkZSBEYXRvcw0KDQojIyMjIFRyYW5zZm9ybWFyIGRhdG9zIGEgbGEgZXN0cnVjdHVyYSB3aWRlDQpgYGB7cn0NCmRhdG9zX3BhcGVyIDwtIHJiaW5kKGRhdG9zX1dCLCBkYXRvc19IREkgJT4lIHNlbGVjdChpbmRpY2F0b3IsIGlzbzJjLCB5ZWFyLCB2YWx1ZSksIFBvdmVydHkpICU+JQ0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gaW5kaWNhdG9yLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKQ0KYGBgDQoNCiMjIyMgUHJvbWVkaW8gZGUgSW5kaWNlcyBkZSBHb2Jlcm5hbnphDQpgYGB7cn0NCmRhdG9zX3BhcGVyIDwtIGRhdG9zX3BhcGVyICU+JSBtdXRhdGUoR09WID0gIChDQy5FU1QgKyBHRS5FU1QgKyBQVi5FU1QgKyBSUS5FU1QgKyBSTC5FU1QgKyBWQS5FU1QpIC8gNikNCmBgYA0KDQojIyMjIE9wZXJhZG9yIERpZmVyZW5jaWENCg0KYGBge3J9DQpkYXRvc19wYXBlciA8LSBkYXRvc19wYXBlciAlPiUgYXJyYW5nZShpc28yYywgeWVhcikgJT4lIA0KICAgICAgICBtdXRhdGUoaGRpX2RpZmYgPSBjYXNlX3doZW4oaXNvMmMgPT0gZHBseXI6OmxhZyhpc28yYykgfiBoZGkgLSBkcGx5cjo6bGFnKGhkaSksIFRSVUUgfiBOQV9yZWFsXyksIA0KICAgICAgICAgICAgICAgTlkuR0RQLlBDQVAuQ0RfZGlmZiA9IGNhc2Vfd2hlbihpc28yYyA9PSBkcGx5cjo6bGFnKGlzbzJjKSB+IE5ZLkdEUC5QQ0FQLkNEIC0gZHBseXI6OmxhZyhOWS5HRFAuUENBUC5DRCksIFRSVUUgfiBOQV9yZWFsXyksDQogICAgICAgICAgICAgICBEVC5PREEuQUxMRC5DRF9kaWZmID0gY2FzZV93aGVuKGlzbzJjID09IGRwbHlyOjpsYWcoaXNvMmMpIH4gRFQuT0RBLkFMTEQuQ0QgLSBkcGx5cjo6bGFnKERULk9EQS5BTExELkNEKSwgVFJVRSB+IE5BX3JlYWxfKSwNCiAgICAgICAgICAgICAgIERULk9EQS5PREFULlBDLlpTX2RpZmYgPSBjYXNlX3doZW4oaXNvMmMgPT0gZHBseXI6OmxhZyhpc28yYykgfiBEVC5PREEuT0RBVC5QQy5aUyAtIGRwbHlyOjpsYWcoRFQuT0RBLk9EQVQuUEMuWlMpLCBUUlVFIH4gTkFfcmVhbF8pLA0KICAgICAgICAgICAgICAgR09WX2RpZmYgPSBjYXNlX3doZW4oaXNvMmMgPT0gZHBseXI6OmxhZyhpc28yYykgfiBHT1YgLSBkcGx5cjo6bGFnKEdPViksIFRSVUUgfiBOQV9yZWFsXyksDQogICAgICAgICAgICAgICBQT1ZfZGlmZiA9IGNhc2Vfd2hlbihpc28yYyA9PSBkcGx5cjo6bGFnKGlzbzJjKSB+IFBPViAtIGRwbHlyOjpsYWcoUE9WKSwgVFJVRSB+IE5BX3JlYWxfKSkNCmBgYA0KDQojIyMjIE9EQQ0KDQpgYGB7cn0NCnZpc19kYXQoZGF0b3NfcGFwZXIgJT4lIHNlbGVjdChhbGxfb2YoZ3N1YigiXyIsICIuIiwgb2RhX2luZGljYXRvcnMpKSkpIA0KICAjIERULk9EQS5PQVRMLkNEIGFuZCBEVC5PREEuT0FUTC5LRCBmYWx0YW4NCiAgIyBEVC5PREEuT0RBVC5HSS5aUywgRFQuT0RBLk9EQVQuR04uWlMsIERULk9EQS5PREFULk1QLlpTIGFuZCBEVC5PREEuT0RBVC5YUC5aUyB0aWVuZW4gZmFsdGFzDQogICMgVW4gcGFyIGRlIG9jdXJyZW5jaWFzIHBhaXMtYcOxbyBxdWUgZmFsdGFuIGRhdG9zDQpgYGANCg0KIyMjIyBHRFANCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSBzZWxlY3QoTlkuR0RQLlBDQVAuQ04sIE5ZLkdEUC5QQ0FQLkNEKSkgDQogICMgTlkuR0RQLlBDQVAuQ04sIE5ZLkdEUC5QQ0FQLkNELCBOWS5HRFAuTUtUUC5DRCwgTlkuR0RQLk1LVFAuQ04gc29uIGJ1ZW5vcyBjYW5kaWRhdG9zIHBhcmEgdXNhciBjb21vIHZhcmlhYmxlcywgDQogICMgJ1NZJ2ZhbHRhIFBJQiBwZXIgQ2FwaXRhIGVuIDIwMjIsIDIwMjMgc2luIGRhdG9zIGFsZ3Vub3MgcGFpc2VzDQpgYGANCg0KIyMjIyBHT1YNCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSBhcnJhbmdlKHllYXIpICU+JSBzZWxlY3QoYWxsX29mKGdzdWIoIl8iLCAiLiIsIGdvYl9pbmRpY2F0b3JzKSkpKSANCiAgIyBEYXRvcyBkZWwgMjAwMCBwYXJhIGF0cmFzIHRpZW5lbiBlc3BhY2lvcyBmYWx0YW50ZXMgDQpgYGANCg0KIyMjIyBIREkNCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSBzZWxlY3QoYWxsX29mKGhkaV9pbmRpY2F0b3JzKSkpIA0KICAjIGFiciwgY28yX3Byb2QsIGxlLCBsZV9mLCBsZV9tLCBtbXIgc29uIGxhcyBwb2NhcyBjYXRlZ29yaWFzIHNpbiBkYXRvcyBmYWx0YW50ZXMNCiAgIyBoZGkgZmFsdGFudGUgZW4gbXVsdGlwbGVzIG9jYWNpb25lcw0KYGBgDQoNCiMjIyMgUE9QLkdST1cNCg0KYGBge3J9DQp2aXNfZGF0KGRhdG9zX3BhcGVyICU+JSBhcnJhbmdlKGlzbzJjKSAlPiUgc2VsZWN0KFNQLlBPUC5HUk9XKSkgDQogICMgWlcgbm8gdGllbmUgZGF0b3MgZGUgY3JlY2ltaWVudG8gcG9ibGFjaW9uYWwNCg0KYGBgDQoNCiMjIyMgUE9WDQoNCmBgYHtyfQ0KdmlzX2RhdChkYXRvc19wYXBlciAlPiUgYXJyYW5nZShpc28yYykgJT4lIHNlbGVjdChQT1YpKSANCiAgIyBIYXkgbXVjaG9zIHBhaXNlcyBzaW4gZGF0b3MNCg0KYGBgDQoNCiMjIE1vZGVsb3MgT0xTIHsudGFic2V0IC50YWJzZXQtZmFkZX0NCg0KIyMjIEZpbHRyb3MgcGFyYSBtb2RlbG8NCg0KYGBge3J9DQojIHZhcmlhYmxlcyBkZSBldGlxdWV0YQ0KdmUgPC0gYygnaXNvMmMnLCAneWVhcicpDQojIHZhcmlhYmxlcyBkZXBuZGllbnRlcw0KdmQgPC0gYygnaGRpJywgJ2hkaV9kaWZmJywgJ05ZLkdEUC5QQ0FQLkNEJywgJ05ZLkdEUC5QQ0FQLkNEX2RpZmYnKQ0KIyB2YXJpYWJsZXMgaW5kZXBlbmRpZW50ZXMNCnZpIDwtIGMoJ0RULk9EQS5BTExELkNEJywgJ0RULk9EQS5BTExELkNEX2RpZmYnLCAnRFQuT0RBLk9EQVQuUEMuWlMnLCAnRFQuT0RBLk9EQVQuUEMuWlNfZGlmZicpDQojIHZhcmlhYmxlcyBkZSBjb250cm9sDQp2YyA8LSBjKCdTUC5QT1AuR1JPVycsICdHT1YnKSAjJ0NDLkVTVCcsICdHRS5FU1QnLCAnUFYuRVNUJywgJ1JRLkVTVCcsICdSTC5FU1QnLCAnVkEuRVNUJywgJ0dPVl9kaWZmJywgJ1BPVicsICdQT1ZfZGlmZicNCg0KIyBwYWlzZXMgc2luIGRhdG9zDQpkZWxldGVfYyA8LSBjKCdTUycsICdaVycsICdCVCcsICdFUicsICdHVycsICdLUCcsICdMQicsICdORycsICdQUycsICdTTycsICdWVScsICdGTScsICdLSScsICdUTCcsICdDVicsICdTQicsICdTWScpDQojIGHDsW9zIHNpbiBkYXRvcw0KZmlyc3RfeSA8LSAyMDAyDQpsYXN0X3kgPC0gMjAyMg0KDQpkYXRvc19tb2RlbCA8LSBkYXRvc19wYXBlciAlPiUgDQogIGZpbHRlcighaXNvMmMgJWluJSBkZWxldGVfYywgIXllYXIgPCAgZmlyc3RfeSwgIXllYXIgPiBsYXN0X3kpICU+JQ0KICBzZWxlY3QoYWxsX29mKGModmUsIHZkLCB2aSwgdmMpKSkNCg0KZGF0b3NfbW9kZWwNCnZpc19kYXQoZGF0b3NfbW9kZWwpDQpgYGANCg0KIyMjIFJlbGFjaW9uZXMgey50YWJzZXQgLnRhYnNldC1mYWRlfQ0KDQpTZSByZXZpc2FyYSBsYXMgcmVsYWNpb25lcyBlbnRyZSBsYXMgdmFyaWFibGVzIGdyYWZpY2FtZW50ZSANCk5vIHNlIHZlIHVuYSByZWxhY2lvbiBjbGFyYSwgaGF5IHRhbnRvIHBhaXNlcyBjb24gcHVudGVvcyBhbHRvcyB5IGJham9zIGRlIEdPQiBxdWUgdGllbmVuIHRhbnRvIEhJRCBhbHRvcyBvIGJham9zIFF1aXphIHB1ZWRlIHZlcnNlIHVuYSBsZXZlIHJlbGFjaW9uIGRlIG1heW9yIHB1bnRlbyBlbiBHT0IgYWNvbXBhw7FhZG8gZGUgbWVqb3IgcHVudGVvIGRlbiBIREkgTG9zIGRhdG9zIGRlIEdQRCBzaSBtdWVzdHJhbiB1bmEgcmVsYWNpb24gcG9zaXRpdmEgY29uIGVsIEhESSB2aXN0byBlbiBsYXMgZ3JhZmljYXMNCg0KIyMjIyBIREkNCg0KYGBge3J9DQpteV9wbG90ID0gbGlzdCgpDQoNCmZvciAodmRfIGluIHZkKSB7DQogIGZvciAodmlfIGluIGModmksIHZjKSl7DQogICAgbXlfcGxvdFtbcGFzdGUodmRfLHZpXyldXSA8LSBwbG90X2x5KHggPSBkYXRvc19tb2RlbFtbdmlfXV0sIHkgPSBkYXRvc19tb2RlbFtbdmRfXV0sIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbWFya2VycycsIG5hbWUgPSBwYXN0ZSh2ZF8sdmlfKSkNCiAgfQ0KfQ0KDQpzdWJwbG90KG15X3Bsb3RbMTo2XSwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjA1KQ0KDQpgYGANCg0KIyMjIyBIREkgZGlmZg0KDQpgYGB7cn0NCnN1YnBsb3QobXlfcGxvdFs3OjEyXSwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjA1KQ0KYGBgDQoNCiMjIyMgR1BELlBDDQoNCmBgYHtyfQ0Kc3VicGxvdChteV9wbG90WzEzOjE4XSwgbnJvd3MgPSAyLCBtYXJnaW4gPSAwLjA1KQ0KYGBgDQoNCg0KIyMjIyBHUEQuUEMgZGlmZg0KDQpgYGB7cn0NCnN1YnBsb3QobXlfcGxvdFsxOToyNl0sIG5yb3dzID0gMiwgbWFyZ2luID0gMC4wNSkNCmBgYA0KDQojIyBNb2RlbG9zIFJlZ3Jlc2lvbiBMaW5lYWwgey50YWJzZXQgLnRhYnNldC1mYWRlfQ0KDQpQcm9iYW5kbyBtb2RlbG9zIHNlbmNpbGxvcywgcmVncmVzaW9uIGxpbmVhbCwgTWluaW1vcyBjdWFkcmFkb3MsIGRhdG9zIHBhbmVsLCBIREkgbyBHRFAgbyBzdXMgZGlmZmVyZWNpYXMNCg0KYGBge3J9DQptb2RlbHMgPC0gbGlzdCgpDQprZXlzIDwtIGNoYXJhY3RlcigpDQpmb3JtdWxhcyA8LSBjaGFyYWN0ZXIoKQ0KZm9yICh2ZF8gaW4gdmQpIHsNCiAgZm9yICh2aV8gaW4gdmkpIHsNCiAgICBrZXkgPC0gcGFzdGUodmRfLCB2aV8sIHNlcCA9ICJ+IikNCiAgICBrZXlzIDwtIGMoa2V5cywga2V5KQ0KICAgIGYgPC0gcGFzdGUodmRfLCAnficsIHZpXywgJysnLCBwYXN0ZSh2YywgY29sbGFwc2UgPSAnICsgJykpDQogICAgZm9ybXVsYXMgPC0gYyhmb3JtdWxhcywgZikgDQogICAgbW9kZWxzW1trZXldXSA8LSBsbShmLCBkYXRhPWRhdG9zX21vZGVsKQ0KICB9DQp9DQpgYGANCg0KIyMjIEhESSB7LnRhYnNldCAudGFic2V0LWZhZGV9DQoNCiMjIyMgT0RBLkFMTA0KDQpgYGB7cn0NCmNhdChmb3JtdWxhc1sxXSkNCnN1bW1hcnkobW9kZWxzW1trZXlzWzFdXV0pDQojIFRvZGFzIGxhcyB2YXJpYWJsZXMgc29uIHNpZ25pZmljYXRpdmFzIGFsIDk5JSBleGNlcHRvIFJlZ3VsYXRvcnkgUXVhbGl0eQ0KYGBgDQoNCg0KIyMjIyBPREEuQUxMX2RpZmYNCg0KSERJID0gT0RBLkFMTF9kaWZmICsgQ0MgKyBHRSArIFBWICsgUlEgKyBSTCArIFZBICsgUE9QLkdST1cNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZGVsc1tba2V5c1syXV1dKQ0KIyBUb2RhcyBsYXMgdmFyaWFibGVzIHNvbiBzaWduaWZpY2F0aXZhcyBhbCA5OSUgZXhjZXB0byBPREEuQUxMX2RpZmYgeSBSZWd1bGF0b3J5IFF1YWxpdHkNCmBgYA0KDQoNCiMjIyMgT0RBLlBDDQoNCkhESSA9IE9EQS5QQyArIENDICsgR0UgKyBQViArIFJRICsgUkwgKyBWQSArIFBPUC5HUk9XDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbHNbW2tleXNbM11dXSkNCiMgVG9kYXMgbGFzIHZhcmlhYmxlcyBzb24gc2lnbmlmaWNhdGl2YXMgYWwgOTklIGV4Y2VwdG8gUmVndWxhdG9yeSBRdWFsaXR5DQpgYGANCg0KDQojIyMjIE9EQS5QQ19kaWZmDQoNCkhESSA9IE9EQS5QQ19kaWZmICsgQ0MgKyBHRSArIFBWICsgUlEgKyBSTCArIFZBICsgUE9QLkdST1cNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZGVsc1tba2V5c1s0XV1dKQ0KIyBUb2RhcyBsYXMgdmFyaWFibGVzIHNvbiBzaWduaWZpY2F0aXZhcyBhbCA5OSUgZXhjZXB0byAgT0RBLkFMTF9kaWZmIHkgUmVndWxhdG9yeSBRdWFsaXR5DQpgYGANCiANCg0KIyMjIEhESV9kaWZmIHsudGFic2V0IC50YWJzZXQtZmFkZX0NCg0KIyMjIyBPREEuQUxMDQoNCkhESV9kaWZmID0gT0RBLkFMTCArIENDICsgR0UgKyBQViArIFJRICsgUkwgKyBWQSArIFBPUC5HUk9XDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbHNbW2tleXNbNV1dXSkNCiMgVG9kYXMgbGFzIHZhcmlhYmxlcyBzb24gc2lnbmlmaWNhdGl2YXMgYWwgOTUlIGV4Y2VwdG8gT0RBLkFMTCwgQ29udHJvbCBvZiBDb3JydXB0aW9uIHkgUnVsZSBvZiBMYXcNCmBgYA0KDQoNCiMjIyMgT0RBLkFMTF9kaWZmDQoNCkhESV9kaWZmID0gT0RBLkFMTF9kaWZmICsgQ0MgKyBHRSArIFBWICsgUlEgKyBSTCArIFZBICsgUE9QLkdST1cNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZGVsc1tba2V5c1s2XV1dKQ0KIyBUb2RhcyBsYXMgdmFyaWFibGVzIHNvbiBzaWduaWZpY2F0aXZhcyBhbCA5NSUgZXhjZXB0byBDb250cm9sIG9mIENvcnJ1cHRpb24geSBWb2ljZSBhbmQgQWNjb3VudGFiaWxpdHkNCmBgYA0KDQoNCiMjIyMgT0RBLlBDDQoNCkhESV9kaWZmID0gT0RBLlBDICsgQ0MgKyBHRSArIFBWICsgUlEgKyBSTCArIFZBICsgUE9QLkdST1cNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZGVsc1tba2V5c1s3XV1dKQ0KIyBUb2RhcyBsYXMgdmFyaWFibGVzIHNvbiBzaWduaWZpY2F0aXZhcyBhbCA5NSUgZXhjZXB0byBSdWxlIG9mIExhdyB5IFZvaWNlIGFuZCBBY2NvdW50YWJpbGl0eQ0KYGBgDQogDQoNCiMjIyMgT0RBLlBDX2RpZmYNCg0KSERJX2RpZmYgPSBPREEuUENfZGlmZiArIENDICsgR0UgKyBQViArIFJRICsgUkwgKyBWQSArIFBPUC5HUk9XDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbHNbW2tleXNbOF1dXSkNCiMgVG9kYXMgbGFzIHZhcmlhYmxlcyBzb24gc2lnbmlmaWNhdGl2YXMgYWwgOTUlIGV4Y2VwdG8gQ29udHJvbCBvZiBDb3JydXB0aW9uIHkgVm9pY2UgYW5kIEFjY291bnRhYmlsaXR5DQpgYGANCg0KIyMjIEdQRC5QQyB7LnRhYnNldCAudGFic2V0LWZhZGV9DQoNCiMjIyMgT0RBLkFMTA0KDQpHUEQuUEMgPSBPREEuQUxMICsgQ0MgKyBHRSArIFBWICsgUlEgKyBSTCArIFZBICsgUE9QLkdST1cNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZGVsc1tba2V5c1s5XV1dKQ0KIyBUb2RhcyBsYXMgdmFyaWFibGVzIHNvbiBzaWduaWZpY2F0aXZhcyBhbCA5OSUgZXhjZXB0byBPREEuQUxMLCBDb250cm9sIG9mIENvcnJ1cHRpb24sIFJlZ3VsYXRvcnkgUXVhbGl0eSB5IFJ1bGUgb2YgTGF3DQpgYGANCg0KIyMjIyBPREEuQUxMX2RpZmYNCg0KR1BELlBDID0gT0RBLkFMTCArIENDICsgR0UgKyBQViArIFJRICsgUkwgKyBWQSArIFBPUC5HUk9XDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbHNbW2tleXNbMTBdXV0pDQojIFRvZGFzIGxhcyB2YXJpYWJsZXMgc29uIHNpZ25pZmljYXRpdmFzIGFsIDk5JSBleGNlcHRvIE9EQS5BTExfZGlmZiwgQ29udHJvbCBvZiBDb3JydXB0aW9uLCBSZWd1bGF0b3J5IFF1YWxpdHkgeSBSdWxlIG9mIExhdw0KYGBgDQoNCiMjIyMgT0RBLlBDDQoNCkdQRC5QQyA9IE9EQS5QQyArIENDICsgR0UgKyBQViArIFJRICsgUkwgKyBWQSArIFBPUC5HUk9XDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbHNbW2tleXNbMTFdXV0pDQojIFRvZGFzIGxhcyB2YXJpYWJsZXMgc29uIHNpZ25pZmljYXRpdmFzIGFsIDk5JSBleGNlcHRvIFJ1bGUgb2YgTGF3DQpgYGANCg0KIyMjIyBPREEuUENfZGlmZg0KDQpHUEQuUEMgPSBPREEuUENfZGlmZiArIENDICsgR0UgKyBQViArIFJRICsgUkwgKyBWQSArIFBPUC5HUk9XDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbHNbW2tleXNbMTJdXV0pDQojIFRvZGFzIGxhcyB2YXJpYWJsZXMgc29uIHNpZ25pZmljYXRpdmFzIGFsIDk5JSBleGNlcHRvIE9EQS5BTExfZGlmZiwgQ29udHJvbCBvZiBDb3JydXB0aW9uLCBSZWd1bGF0b3J5IFF1YWxpdHkgeSBSdWxlIG9mIExhdw0KYGBgDQoNCiMjIyBHUEQuUENfZGlmZiB7LnRhYnNldCAudGFic2V0LWZhZGV9DQoNCiMjIyMgT0RBLkFMTA0KDQpHUEQuUENfZGlmZiA9IE9EQS5BTEwgKyBDQyArIEdFICsgUFYgKyBSUSArIFJMICsgVkEgKyBQT1AuR1JPVw0KDQpgYGB7cn0NCnN1bW1hcnkobW9kZWxzW1trZXlzWzEzXV1dKQ0KIyBUb2RhcyBsYXMgdmFyaWFibGVzIHNvbiBzaWduaWZpY2F0aXZhcyBhbCA5NSUgZXhjZXB0byBPREEuQUxMLCBDb250cm9sIG9mIENvcnJ1cHRpb24sIFJlZ3VsYXRvcnkgUXVhbGl0eSB5IFZvaWNlIGFuZCBBY2NvdW50YWJpbGl0eQ0KYGBgDQoNCiMjIyMgT0RBLkFMTF9kaWZmDQoNCkdQRC5QQ19kaWZmID0gT0RBLkFMTCArIENDICsgR0UgKyBQViArIFJRICsgUkwgKyBWQSArIFBPUC5HUk9XDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbHNbW2tleXNbMTRdXV0pDQojIFRvZGFzIGxhcyB2YXJpYWJsZXMgc29uIHNpZ25pZmljYXRpdmFzIGFsIDk1JSBleGNlcHRvIE9EQS5BTExfZGlmZiwgQ29udHJvbCBvZiBDb3JydXB0aW9uLCBSZWd1bGF0b3J5IFF1YWxpdHkgeSBWb2ljZSBhbmQgQWNjb3VudGFiaWxpdHkNCmBgYA0KDQojIyMjIE9EQS5QQw0KDQpHUEQuUENfZGlmZiA9IE9EQS5QQyArIENDICsgR0UgKyBQViArIFJRICsgUkwgKyBWQSArIFBPUC5HUk9XDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbHNbW2tleXNbMTVdXV0pDQojIFRvZGFzIGxhcyB2YXJpYWJsZXMgc29uIHNpZ25pZmljYXRpdmFzIGFsIDk1JSBleGNlcHRvIE9EQS5QQywgQ29udHJvbCBvZiBDb3JydXB0aW9uLCBQb2xpdGljYWwgU3RhYmlsaXR5LCBSZWd1bGF0b3J5IFF1YWxpdHkgeSBWb2ljZSBhbmQgQWNjb3VudGFiaWxpdHkNCmBgYA0KDQojIyMjIE9EQS5QQ19kaWZmDQoNCkdQRC5QQ19kaWZmID0gT0RBLlBDX2RpZmYgKyBDQyArIEdFICsgUFYgKyBSUSArIFJMICsgVkEgKyBQT1AuR1JPVw0KDQpgYGB7cn0NCnN1bW1hcnkobW9kZWxzW1trZXlzWzE2XV1dKQ0KIyBUb2RhcyBsYXMgdmFyaWFibGVzIHNvbiBzaWduaWZpY2F0aXZhcyBhbCA5NSUgZXhjZXB0byBPREEuUENfZGlmZiwgQ29udHJvbCBvZiBDb3JydXB0aW9uLCBSZWd1bGF0b3J5IFF1YWxpdHkgeSBWb2ljZSBhbmQgQWNjb3VudGFiaWxpdHkNCmBgYA0KDQoNCiMjIE1vZGVsb3MgRWZlY3RvcyBmaWpvcyB7LnRhYnNldCAudGFic2V0LWZhZGV9DQoNCiMjIyBIREkgXH4gT0RBLkFMTA0KDQpgYGB7cn0NCnBsbShoZGkgfiBEVC5PREEuQUxMRC5DRCArIEdPViArIFNQLlBPUC5HUk9XLCBkYXRhPWRhdG9zX21vZGVsLA0KICAgIGluZGV4ID0gYygiaXNvMmMiLCAieWVhciIpLCBtb2RlbCA9ICJ3aXRoaW4iKQ0KDQojIHN1bW1hcnkobG0oaGRpIH4gRFQuT0RBLkFMTEQuQ0QgKyBDQy5FU1QgKyBHRS5FU1QgKyBQVi5FU1QgKyBSUS5FU1QgKyBSTC5FU1QgKyBWQS5FU1QgKyBTUC5QT1AuR1JPVyArIGlzbzJjLCBkYXRhPWRhdG9zX21vZGVsKSkNCiMgQ29ycnVwdGlvbiBDb250cm9sLCBHb3Zlcm5tZW50IEVmZmVjdGl2ZW5lc3MsIFBvbGl0aWNhbCBTdGFiaWxpdHkgeSBWb2ljZSBhbmQgQWNjb3VudGFiaWxpdHkgbm8gc29uIHNpZ25pZmljYXRpdmFzDQpgYGANCg0KIyMjIEhESSBcfiBPREEuUEMNCg0KYGBge3J9DQpwbG0oaGRpIH4gRFQuT0RBLk9EQVQuUEMuWlMgKyBHT1YgKyBTUC5QT1AuR1JPVywgZGF0YT1kYXRvc19tb2RlbCwNCiAgICBpbmRleCA9IGMoImlzbzJjIiwgInllYXIiKSwgbW9kZWwgPSAid2l0aGluIikNCg0KI3N1bW1hcnkobG0oaGRpIH4gRFQuT0RBLk9EQVQuUEMuWlMgKyBDQy5FU1QgKyBHRS5FU1QgKyBQVi5FU1QgKyBSUS5FU1QgKyBSTC5FU1QgKyBWQS5FU1QgKyBTUC5QT1AuR1JPVyArIGlzbzJjLCBkYXRhPWRhdG9zX21vZGVsKSkNCiMgQ29ycnVwdGlvbiBDb250cm9sLCBHb3Zlcm5tZW50IEVmZmVjdGl2ZW5lc3MgeSBWb2ljZSBhbmQgQWNjb3VudGFiaWxpdHkgbm8gc29uIHNpZ25pZmljYXRpdmFzDQpgYGANCg0KIyMjIEdEUC5QQyBcfiBPREEuQUxMDQoNCmBgYHtyfQ0KcGxtKE5ZLkdEUC5QQ0FQLkNEIH4gRFQuT0RBLkFMTEQuQ0QgKyBHT1YgKyBTUC5QT1AuR1JPVywgZGF0YT1kYXRvc19tb2RlbCwNCiAgICBpbmRleCA9IGMoImlzbzJjIiwgInllYXIiKSwgbW9kZWwgPSAid2l0aGluIikNCg0KI3N1bW1hcnkobG0oTlkuR0RQLlBDQVAuQ0QgfiBEVC5PREEuQUxMRC5DRCArIENDLkVTVCArIEdFLkVTVCArIFBWLkVTVCArIFJRLkVTVCArIFJMLkVTVCArIFZBLkVTVCArIFNQLlBPUC5HUk9XICsgaXNvMmMsIGRhdGE9ZGF0b3NfbW9kZWwpKQ0KIyBJbnRlcmNlcHRvLCBDb3JydXB0aW9uIENvbnRyb2wsIFJlZ3VsYXRvcnkgUXVhbGl0eSwgUnVsZSBvZiBMYXcsIFZvaWNlIGFuZCBBY2NvdW50YWJpbGl0eSB5IFBvcHVsYXRpb24gR3Jvd3RoIG5vIHNvbiBzaWduaWZpY2F0aXZhcw0KYGBgDQoNCiMjIyBHRFAuUEMgXH4gT0RBLlBDDQoNCmBgYHtyfQ0KcGxtKE5ZLkdEUC5QQ0FQLkNEIH4gRFQuT0RBLk9EQVQuUEMuWlMgKyBHT1YgKyBTUC5QT1AuR1JPVywgZGF0YT1kYXRvc19tb2RlbCwNCiAgICBpbmRleCA9IGMoImlzbzJjIiwgInllYXIiKSwgbW9kZWwgPSAid2l0aGluIikNCg0KI3N1bW1hcnkobG0oTlkuR0RQLlBDQVAuQ0QgfiBEVC5PREEuT0RBVC5QQy5aUyArIENDLkVTVCArIEdFLkVTVCArIFBWLkVTVCArIFJRLkVTVCArIFJMLkVTVCArIFZBLkVTVCArIFNQLlBPUC5HUk9XICsgaXNvMmMsIGRhdGE9ZGF0b3NfbW9kZWwpKQ0KIyBDb3JydXB0aW9uIENvbnRyb2wsIFJlZ3VsYXRvcnkgUXVhbGl0eSwgUnVsZSBvZiBMYXcgeSBWb2ljZSBhbmQgQWNjb3VudGFiaWxpdHkgbm8gc29uIHNpZ25pZmljYXRpdmFzDQpgYGANCg==